package master

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"strconv"
	"study-crontab/crontab/common"
	"time"
)

var G_apiServer *ApiServer

// ApiServer 任务的HTTP接口
type ApiServer struct {
	httpServer *http.Server
}

//保存任务接口
// POST job={"name": "job1", "command": "echo hello", "cronExpr": "* * * * *"}
func handleJobSave(resp http.ResponseWriter, req *http.Request) {
	//任务保存到etcd中
	var (
		err     error
		postJob string
		job     common.Job
		oldJob  *common.Job
	)
	//1.解析POST表单
	if err = req.ParseForm(); err != nil {
		common.BuildResponse(resp, -1, err.Error(), nil)
		return
	}
	// 2, 取表单中的job字段
	postJob = req.PostForm.Get("job")
	// 3, 反序列化job
	if err = json.Unmarshal([]byte(postJob), &job); err != nil {
		fmt.Println("反序列化表单失败", err)
		common.BuildResponse(resp, -1, err.Error(), nil)
		return
	}
	// 4, 保存到etcd
	if oldJob, err = G_jobMgr.SaveJob(&job); err != nil {
		fmt.Println("保存数据到etcd失败", err)
		//返回异常应答
		common.BuildResponse(resp, -1, err.Error(), nil)
		return
	}
	// 5, 返回正常应答 ({"errno": 0, "msg": "", "data": {....}})
	common.BuildResponse(resp, 0, "success", oldJob)
	return
}

//删除任务接口
// POST name=job1
func handleJobDelete(resp http.ResponseWriter, req *http.Request) {
	//任务从etcd中删除
	var (
		err      error
		postName string
		oldJob   *common.Job
	)
	//1.解析POST表单
	if err = req.ParseForm(); err != nil {
		common.BuildResponse(resp, -1, err.Error(), nil)
		return
	}
	// 2, 取表单中的name字段
	postName = req.PostForm.Get("name")
	// 3, etcd删除
	if oldJob, err = G_jobMgr.DeleteJob(postName); err != nil {
		fmt.Println("etcd删除数据失败", err)
		//返回异常应答
		common.BuildResponse(resp, -1, err.Error(), nil)
		return
	}
	// 5, 返回正常应答 ({"errno": 0, "msg": "", "data": {....}})
	common.BuildResponse(resp, 0, "success", oldJob)
	return
}

//获取所有任务接口
func handleJobList(resp http.ResponseWriter, req *http.Request) {
	//获取etcd中所有任务
	var (
		err     error
		jobList []*common.Job
	)

	// 1, etcd获取所有数据
	if jobList, err = G_jobMgr.ListJob(); err != nil {
		fmt.Println("etcd获取所有数据失败", err)
		//返回异常应答
		common.BuildResponse(resp, -1, err.Error(), nil)
		return
	}
	// 5, 返回正常应答 ({"errno": 0, "msg": "", "data": {....}})
	common.BuildResponse(resp, 0, "success", jobList)
	return
}

//停止任务接口
func handleJobKill(resp http.ResponseWriter, req *http.Request) {
	//停止任务
	var (
		err     error
		jobList []*common.Job
	)

	//1.解析POST表单
	if err = req.ParseForm(); err != nil {
		common.BuildResponse(resp, -1, err.Error(), nil)
		return
	}
	postName := req.PostForm.Get("name")
	// 2, etcd获取所有数据
	if err = G_jobMgr.KillJob(postName); err != nil {
		fmt.Printf("杀死任务%s失败%v", postName, err)
		//返回异常应答
		common.BuildResponse(resp, -1, err.Error(), nil)
		return
	}
	// 5, 返回正常应答 ({"errno": 0, "msg": "", "data": {....}})
	common.BuildResponse(resp, 0, "success", jobList)
	return
}

// InitApiServer 初始化服务
func InitApiServer() error {
	//配置路由
	mux := http.NewServeMux()
	mux.HandleFunc("/job/save", handleJobSave)
	mux.HandleFunc("/job/delete", handleJobDelete)
	mux.HandleFunc("/job/list", handleJobList)
	mux.HandleFunc("/job/kill", handleJobKill)
	mux.HandleFunc("/job/log", handleJobLog)
	mux.HandleFunc("/worker/list", handleWorkerList)

	//静态文件
	staticDir := http.Dir(G_config.Webroot)
	staticHandler := http.FileServer(staticDir)
	mux.Handle("/", http.StripPrefix("/", staticHandler))

	//启动tcp监听
	listener, err := net.Listen("tcp", ":"+strconv.Itoa(G_config.ApiPort))
	if err != nil {
		fmt.Println("启动api服务失败", err)
		return err
	}

	server := &http.Server{
		ReadTimeout:  time.Duration(G_config.ApiReadTimeout) * time.Millisecond,
		WriteTimeout: time.Duration(G_config.ApiWriteTimeout) * time.Millisecond,
		Handler:      mux,
	}

	G_apiServer = &ApiServer{
		httpServer: server,
	}

	//启动了服务端
	go server.Serve(listener)

	return nil
}

//查询任务日志
func handleJobLog(resp http.ResponseWriter, req *http.Request) {
	var (
		err   error
		skip  int
		limit int
	)
	//1.解析表单
	if err = req.ParseForm(); err != nil {
		common.BuildResponse(resp, -1, err.Error(), nil)
		return
	}
	//查询参数
	name := req.Form.Get("name")
	skipPram := req.Form.Get("skip")
	limitPram := req.Form.Get("limit")

	skip, err = strconv.Atoi(skipPram)
	if err != nil {
		skip = 0
	}

	limit, err = strconv.Atoi(limitPram)
	if err != nil {
		limit = 20
	}

	logArr, err := G_logMgr.ListLog(name, skip, limit)
	if err != nil {
		common.BuildResponse(resp, -1, err.Error(), nil)
		return
	}
	common.BuildResponse(resp, 0, "success", logArr)
	return
}

//获取健康worker节点
func handleWorkerList(resp http.ResponseWriter, req *http.Request) {
	//停止任务
	var (
		err       error
		workerArr []string
	)

	// 1, etcd获取所有数据
	if workerArr, err = G_workerMgr.ListWorkers(); err != nil {
		common.BuildResponse(resp, -1, err.Error(), nil)
		return
	}
	// 5, 返回正常应答 ({"errno": 0, "msg": "", "data": {....}})
	common.BuildResponse(resp, 0, "success", workerArr)
	return
}
